﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Zyg.Utility.Helper
{
    public static class StringHelper
    {
        #region Fields

        private static readonly string emailReg = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
        private static readonly string imageReg = @".[jpe?g|gif|bmp|png]$";
        private static readonly string ipv4Reg = @"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$";
        private static readonly string ipv6Reg = @"^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$";
        private static readonly string urlReg = @"^(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&amp;%\$#\=~_\-]+))*$";
        private static readonly string webPageReg = @"^([\w-\.\\\/]+).[htm(l)?|asp(x)?|jsp|do|php]$";

        #endregion

        /// <summary>
        /// Validate a string is not null or empty
        /// </summary>
        public static bool IsNullOrEmpty(this String str)
        {
            return String.IsNullOrEmpty(str.Trim());
        }

        /// <summary>
        /// Validate a string is in an email format
        /// </summary>
        public static bool IsEmail(this String str)
        {
            return Regex.IsMatch(str, emailReg);
        }

        /// <summary>
        /// Validate a string is in an image file format.
        /// </summary>
        public static bool IsImage(this String str)
        {
            return Regex.IsMatch(str.ToLower(), imageReg);
        }

        /// <summary>
        /// Validate a string is in an ip(such as 127.0.0.1) format.
        /// </summary>
        public static bool IsIP(this String str)
        {
            return Regex.IsMatch(str, ipv4Reg) || Regex.IsMatch(str, ipv6Reg);
        }

        /// <summary>
        /// Validate a string is in an url(including http://localhost) format.
        /// </summary>
        public static bool IsUrl(this String str)
        {
            return Regex.IsMatch(str, urlReg);
        }

        /// <summary>
        /// Validate a string is in an web page format
        /// </summary>
        public static bool IsWebPage(this String str)
        {
            return Regex.IsMatch(str, webPageReg);
        }

        /// <summary>
        /// Validate a string's length is the specificated bound.
        /// </summary>
        /// <param name="min">min bound of string's length</param>
        /// <param name="max">max bound of string's lendth</param>
        /// <param name="byteCheck">whether check by byte count.</param>
        public static bool IsInLengthBound(this String str, int min, int max, bool byteCheck)
        {
            if (!byteCheck)
            {
                return str.Length >= min && str.Length < max;
            }
            else
            {
                int count = System.Text.Encoding.UTF8.GetByteCount(str);

                return count >= min && min < max;
            }
        }

        /// <summary>
        /// Validate a string's length is the specificated bound.
        /// </summary>
        /// <param name="min">min bound of string's length</param>
        /// <param name="max">max bound of string's lendth</param>
        public static bool IsInLengthBound(this String str, int min, int max)
        {
            return str.IsInLengthBound(min, max, false);
        }

        /// <summary>
        /// Parse a string to Guid.
        /// </summary>
        /// <param name="success">Out value that represent whether the parsing success or not.</param>
        public static Guid ToGuid(this String str, out bool success)
        {
            if (str.IsNullOrEmpty())
            {
                success = false;
                return Guid.Empty;
            }
            else
            {
                Guid id = Guid.Empty;
                try
                {
                    success = true;
                    id = new Guid(str);
                }
                catch
                {
                    success = false;
                }

                return id;
            }
        }
    }
}
